package com.efrei.uchat.server.strategies;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.efrei.uchat.exception.UChatException;
import com.efrei.uchat.io.Session;
import com.efrei.uchat.message.CroomMessage;
import com.efrei.uchat.message.CroomUsersMessage;
import com.efrei.uchat.message.Message;
import com.efrei.uchat.model.croom.Croom;
import com.efrei.uchat.model.croom.CroomMessageStatus;
import com.efrei.uchat.server.UChatServer;

public class CroomWorker implements MessageStrategy {
	
	private static Logger logger = Logger.getLogger(CroomWorker.class);

	@Override
	public List<Message> manage(Message message, UChatServer context)
			throws UChatException {
		List<Message> lst = new ArrayList<Message>();
		Message ret = null;
		
		CroomMessage croomMessage = (CroomMessage) message;
		String topic = croomMessage.getCroom();
		String password = croomMessage.getPassword();
		
		// lock sessions
		try {
			context.getSessionsLock().lock();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Session session = context.getSessions().getSession(message.getSessionId());
		if(session==null) {
			logger.error("invalid null session "+message.getSessionId()
					+" for croom operation");
		}

		// lock crooms
		try {
			context.getCroomsLock().lock();
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new UChatException("error while blocking crooms lock");
		}
		
		try {
			switch (croomMessage.getStatus()) {
			case JOIN:
				ret = croomMessage.response(
						// return response from crooms manager
						context.getCrooms().joinCroom(session, topic, password));
				if(((CroomMessage)ret).getStatus()==CroomMessageStatus.SUCCESS) {
					Croom croom = context.getCrooms().getCroom(topic);
					// notify other users
					for (Session otherSession : croom.getSessions()) {
						CroomUsersMessage msg =
								new CroomUsersMessage(
										otherSession.getId(), croom.getTopic());
						for (Session ss : croom.getSessions()) {
							msg.addSession(ss);
						}
						lst.add(msg);
					}
				}
				break;
			case LEAVE:
				Croom croom = context.getCrooms().getCroom(topic);
				if(croom!=null) {
					croom.removeSession(session);
					if(croom.getNbSessions()==0) {
						// delete empty croom
						logger.info("Delete empty croom "+croom);
						if(context.getCrooms().remove(croom.getTopic())==null) {
							logger.error("Error during croom delete "+croom);
						}
					} else {
						// notify users croom
						for (Session otherSession : croom.getSessions()) {
							// send croom's users
							CroomUsersMessage msg =
									new CroomUsersMessage(
											otherSession.getId(), croom.getTopic());
							for (Session ss : croom.getSessions()) {
								msg.addSession(ss);
							}
							lst.add(msg);
						}
					}
				} else {
					logger.error("invalid null croom for leave "+croom);
				}
				break;
			default:
				throw new UChatException(
						"Unexpected croomMessage status "+
								croomMessage.getStatus().toString());
			}
		} finally {
			context.getCroomsLock().unlock();
			context.getSessionsLock().unlock();
		}
		
		if(ret!=null)
			lst.add(ret);
		return lst;
	}
}
